const { PrismaClient } = require('@prisma/client');
const https = require('https');

const prisma = new PrismaClient();

// 配置选项
const FORCE_RESET = true; // 设置为true将清空现有记录重新导入

// CoinGecko API配置
const COINGECKO_API_BASE = 'https://api.coingecko.com/api/v3';
const ITEMS_PER_PAGE = 250; // CoinGecko每页最多250个

// 请求延迟（避免速率限制）
const REQUEST_DELAY = 1000; // 1秒

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function fetchFromCoinGecko(url) {
  return new Promise((resolve, reject) => {
    https.get(url, {
      headers: {
        'User-Agent': 'ChainWatch-Monitor/1.0',
        'Accept': 'application/json'
      }
    }, (res) => {
      let data = '';
      
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        try {
          if (res.statusCode === 200) {
            resolve(JSON.parse(data));
          } else if (res.statusCode === 429) {
            console.log('⚠️ 遇到速率限制，等待60秒...');
            setTimeout(() => {
              reject(new Error('Rate limited'));
            }, 60000);
          } else {
            reject(new Error(`HTTP ${res.statusCode}: ${data}`));
          }
        } catch (error) {
          reject(error);
        }
      });
    }).on('error', reject);
  });
}

async function fetchTop1000Tokens() {
  console.log('🚀 开始获取CoinGecko前1000名代币...\n');
  
  const allTokens = [];
  let totalPages = 4; // 1000 ÷ 250 = 4页
  
  for (let page = 1; page <= totalPages; page++) {
    try {
      console.log(`📄 正在获取第 ${page}/${totalPages} 页代币...`);
      
      const url = `${COINGECKO_API_BASE}/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${ITEMS_PER_PAGE}&page=${page}&sparkline=false&price_change_percentage=24h`;
      
      const pageData = await fetchFromCoinGecko(url);
      
      if (Array.isArray(pageData) && pageData.length > 0) {
        console.log(`✅ 第${page}页获取成功: ${pageData.length} 个代币`);
        
        // 转换数据格式
        const tokens = pageData.map(token => ({
          symbol: (token.symbol || '').toUpperCase(),
          name: token.name || '',
          coingeckoId: token.id || '',
          marketCapRank: token.market_cap_rank || null,
          marketCap: token.market_cap || null,
          currentPrice: token.current_price || null,
          priceChange24h: token.price_change_percentage_24h || null,
          volume24h: token.total_volume || null,
          isActive: true,
          minValueUsd: 10000 // 默认最小监控金额 $10,000
        }));
        
        allTokens.push(...tokens);
        
        // 显示一些示例代币
        if (page === 1) {
          console.log('📊 前10名代币预览:');
          tokens.slice(0, 10).forEach((token, index) => {
            console.log(`  ${index + 1}. ${token.symbol} (${token.name}) - 排名: ${token.marketCapRank}`);
          });
          console.log('');
        }
      } else {
        console.log(`⚠️ 第${page}页数据为空或格式错误`);
      }
      
      // 请求间延迟
      if (page < totalPages) {
        console.log(`⏳ 等待 ${REQUEST_DELAY/1000} 秒后继续...\n`);
        await delay(REQUEST_DELAY);
      }
      
    } catch (error) {
      console.error(`❌ 获取第${page}页失败:`, error.message);
      
      if (error.message.includes('Rate limited')) {
        console.log('⏳ 速率限制，等待1分钟后重试...');
        await delay(60000);
        page--; // 重试当前页
        continue;
      }
      
      // 其他错误，跳过当前页
      console.log(`⏭️ 跳过第${page}页，继续下一页...\n`);
    }
  }
  
  console.log(`\n🎉 代币获取完成！共获取到 ${allTokens.length} 个代币\n`);
  return allTokens;
}

async function saveTokensToDatabase(tokens) {
  console.log('💾 开始保存代币到数据库...');
  
  let successCount = 0;
  let errorCount = 0;
  
  // 批量处理，每次100个
  const batchSize = 100;
  const totalBatches = Math.ceil(tokens.length / batchSize);
  
  for (let i = 0; i < totalBatches; i++) {
    const start = i * batchSize;
    const end = Math.min(start + batchSize, tokens.length);
    const batch = tokens.slice(start, end);
    
    console.log(`📦 处理批次 ${i + 1}/${totalBatches} (${start + 1}-${end}/${tokens.length})`);
    
    for (const tokenData of batch) {
      try {
        // 验证必要字段
        if (!tokenData.symbol || !tokenData.name || !tokenData.coingeckoId) {
          console.log(`⚠️ 跳过无效代币: ${JSON.stringify(tokenData)}`);
          continue;
        }
        
        if (FORCE_RESET) {
          // 强制重置模式：直接创建新记录
          await prisma.monitoredToken.create({
            data: {
              symbol: tokenData.symbol,
              name: tokenData.name,
              coingeckoId: tokenData.coingeckoId,
              marketCapRank: tokenData.marketCapRank,
              marketCap: tokenData.marketCap,
              currentPrice: tokenData.currentPrice,
              priceChange24h: tokenData.priceChange24h,
              volume24h: tokenData.volume24h,
              isActive: tokenData.isActive,
              minValueUsd: tokenData.minValueUsd
            }
          });
        } else {
          // 更新模式：检查排名后upsert
          // 检查是否已存在相同symbol的记录
          const existingToken = await prisma.monitoredToken.findUnique({
            where: { symbol: tokenData.symbol },
            select: { marketCapRank: true, symbol: true, name: true }
          });

          // 如果存在记录且当前记录的排名更差（数字更大），则跳过
          if (existingToken && 
              existingToken.marketCapRank && 
              tokenData.marketCapRank && 
              existingToken.marketCapRank < tokenData.marketCapRank) {
            console.log(`⏭️ 跳过 ${tokenData.symbol}: 现有记录排名更高 (${existingToken.marketCapRank} vs ${tokenData.marketCapRank})`);
            continue;
          }

          await prisma.monitoredToken.upsert({
            where: { symbol: tokenData.symbol },
            update: {
              name: tokenData.name,
              coingeckoId: tokenData.coingeckoId,
              marketCapRank: tokenData.marketCapRank,
              marketCap: tokenData.marketCap,
              currentPrice: tokenData.currentPrice,
              priceChange24h: tokenData.priceChange24h,
              volume24h: tokenData.volume24h,
              lastPriceUpdate: new Date(),
              updatedAt: new Date()
            },
            create: {
              symbol: tokenData.symbol,
              name: tokenData.name,
              coingeckoId: tokenData.coingeckoId,
              marketCapRank: tokenData.marketCapRank,
              marketCap: tokenData.marketCap,
              currentPrice: tokenData.currentPrice,
              priceChange24h: tokenData.priceChange24h,
              volume24h: tokenData.volume24h,
              isActive: tokenData.isActive,
              minValueUsd: tokenData.minValueUsd
            }
          });
        }
        
        successCount++;
        
        // 显示进度
        if (successCount % 50 === 0) {
          console.log(`  ✅ 已成功处理 ${successCount} 个代币`);
        }
        
      } catch (error) {
        errorCount++;
        console.error(`❌ 保存代币 ${tokenData.symbol} 失败:`, error.message);
        
        // 如果错误太多，停止处理
        if (errorCount > 50) {
          console.error('❌ 错误过多，停止处理');
          break;
        }
      }
    }
    
    // 批次间小延迟
    if (i < totalBatches - 1) {
      await delay(100);
    }
  }
  
  console.log(`\n📊 数据库保存完成:`);
  console.log(`  ✅ 成功: ${successCount} 个代币`);
  console.log(`  ❌ 失败: ${errorCount} 个代币`);
  
  return { successCount, errorCount };
}

async function displayStats() {
  try {
    const stats = await prisma.monitoredToken.aggregate({
      _count: {
        id: true
      }
    });
    
    const activeCount = await prisma.monitoredToken.count({
      where: { isActive: true }
    });
    
    const topTokens = await prisma.monitoredToken.findMany({
      take: 10,
      orderBy: { marketCapRank: 'asc' },
      select: {
        symbol: true,
        name: true,
        marketCapRank: true,
        currentPrice: true,
        isActive: true
      }
    });
    
    console.log(`\n📈 数据库统计:`);
    console.log(`  总代币数: ${stats._count.id}`);
    console.log(`  活跃代币数: ${activeCount}`);
    console.log(`\n🏆 市值前10名代币:`);
    
    topTokens.forEach((token, index) => {
      const status = token.isActive ? '🟢' : '🔴';
      const price = token.currentPrice ? `$${token.currentPrice.toLocaleString()}` : 'N/A';
      console.log(`  ${index + 1}. ${status} ${token.symbol} (${token.name}) - 排名: ${token.marketCapRank}, 价格: ${price}`);
    });
    
  } catch (error) {
    console.error('获取统计信息失败:', error);
  }
}

async function main() {
  console.log('🏁 ChainWatch - 代币监控列表初始化\n');
  console.log('📋 功能说明:');
  console.log('  - 从CoinGecko获取市值前1000名代币');
  console.log('  - 保存到数据库monitored_tokens表');
  console.log('  - 设置默认监控阈值为$10,000');
  console.log('  - 后续可通过管理界面调整具体代币的监控参数\n');
  
  try {
    // 检查数据库连接
    console.log('🔗 检查数据库连接...');
    await prisma.$connect();
    console.log('✅ 数据库连接成功\n');
    
    // 检查是否已有数据
    const existingCount = await prisma.monitoredToken.count();
    if (existingCount > 0) {
      console.log(`⚠️ 数据库中已有 ${existingCount} 个代币记录`);
      
      if (FORCE_RESET) {
        console.log('🗑️ FORCE_RESET=true，正在清空现有记录...');
        const deleteResult = await prisma.monitoredToken.deleteMany({});
        console.log(`✅ 已删除 ${deleteResult.count} 个记录\n`);
      } else {
        console.log('📝 此脚本将更新现有记录或插入新记录\n');
      }
    }
    
    // 获取代币数据
    const tokens = await fetchTop1000Tokens();
    
    if (tokens.length === 0) {
      console.log('❌ 未获取到任何代币数据，脚本退出');
      return;
    }
    
    // 保存到数据库
    const result = await saveTokensToDatabase(tokens);
    
    // 显示统计信息
    await displayStats();
    
    console.log('\n🎉 初始化完成！');
    console.log('📝 接下来你可以:');
    console.log('  1. 通过管理界面调整特定代币的监控阈值');
    console.log('  2. 启用/禁用特定代币的监控');
    console.log('  3. 重新运行此脚本来更新代币数据');
    
  } catch (error) {
    console.error('❌ 初始化失败:', error);
    console.error('\n💡 可能的解决方案:');
    console.error('  1. 检查网络连接');
    console.error('  2. 检查数据库配置');
    console.error('  3. 运行 npx prisma db push 来创建数据表');
    console.error('  4. 稍后重试（避免CoinGecko API速率限制）');
  } finally {
    await prisma.$disconnect();
  }
}

// 处理脚本中断
process.on('SIGINT', async () => {
  console.log('\n⚠️ 脚本被中断');
  await prisma.$disconnect();
  process.exit(0);
});

process.on('unhandledRejection', async (error) => {
  console.error('❌ 未处理的Promise拒绝:', error);
  await prisma.$disconnect();
  process.exit(1);
});

// 运行主函数
main(); 